package com.mycompany.project.client;

import com.smartgwt.client.types.DragAppearance;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.TextArea;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.types.AnimationEffect;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.widgets.events.ResizedHandler;
import com.smartgwt.client.widgets.events.ResizedEvent;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.events.MouseOverHandler;
import com.smartgwt.client.widgets.events.MouseOverEvent;
import com.smartgwt.client.widgets.events.MouseOutHandler;
import com.smartgwt.client.widgets.events.MouseOutEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.FocusEvent;


/**
 * @author Laboratorio Tv Collaborativa/Contenuti Digitali --> Sardegna District --> Crs4 --> Sardegna Ricerche
 * 
 * This Class Implements a Text Box container like a post-it object. This text box
 * is graphically similar at Post-It where you can enter notes. As in the Post-It
 * in this box container you can insert the electronics notes. In @SaStria project
 * this object is used to write and insert the note about the video Annotation, so
 * it is the visible annotation Tag showed on player of @SaStria annotations tool. 
 * This Text box can be moved, dragged, resized, for cover all' interesting Video Area.
 */
public class AnnotationTag extends VLayout{
	private static final int borderSize=15;    //Size in pixel of annotation box container. 10px for text area container + "5px" for text area
	private static final int animateDuration=700;   // Length in milliseconds for the opening and closing animation of annotation Tag  
	private boolean isOpened;   // if true the Annotation tag is visible on video player. false otherwise.
	private HandlerManager handleManagerSaved;  // handle manager for fire the AnnotationSaveEvent and consequently the onAnnotationSaved event 
	private HandlerManager handleManagerTextChange; // handle manager for fire the AnnotationDescrTextChangeEvent and consequently the onTextChange event
	private HandlerManager handleManagerAnnotKeyWordBlur; // handle manager for fire the AnnotationKeywordBlurEventHandler and consequently the onAnnotationKeyWordBlur event
	private TextArea textArea;
	private Label lblSaStria;
	private int annotationPreviewIndex; // index of annotation preview on annotation preview panel list.
	private double annotationTimeEnd;    // annotation video segment end time. 
	private double annotationTimeStart;  // annotation video segment start time.
	FlexTable panelKeyword;    // keyword text box panel container
	FlexTable panelDescription; // description text box panel container
	TextBox textBoxKeyword; // Text box panel container
	String keyWordValue; // Key Word value saved when textBoxKeyword get focus. it's used to compare the value when get and lost focus 
	
	
	/**
	 * This methods set the dimension of the Annotation Text Area according with the AnnotationTextContainer size.
	 * The AnnotationTextContainer is the container box of TextArea component 
	 */
	private void setDimmension(){
		int width=this.getWidth() - 2*borderSize;
		int height=this.getHeight() - 2*borderSize;
	    panelKeyword.setSize(width +"px","10px");
	    panelDescription.setSize(width+"px", (height-45)+"px");
		lblSaStria.setTop(height-10);
		//Window.alert("SetDimmension eseguito");
	}
	
	
	/**
	 * This is the constructor of this class that create the AnnotationTag object.
	 * The annotationTag object is visually divided in two layer, Top and bottom layer.
	 * Top Layer deals the 100% available space in Horizontally and the (100% - 20px) in
	 * vertically. It show the annotationTextContainer container and the annotationArea text Box.
	 * Bottom layer deals the 100% available space in Horizontally and 20px in vertically. 
	 * It show the label without no function(only for good looking) that contain the 
	 * word @SaStria. 
	 * This constructor also sets the coordinate position X and Y within the media player area.   
	 * @param xPos: integer value indicating the X position coordinate within the media player area
	 * used for set the x position of annotationTag
	 * @param yPos: : integer value indicating the Y position coordinate within the media player area
	 * used for set the Y position of annotationTag 
	 * @param previewIndex:  index of annotation preview on annotation preview panel list.
	 */
	public AnnotationTag(int xPos,int yPos,int previewIndex,double timeS,double timeE) {
		annotationTimeStart=timeS;
		annotationTimeEnd=timeE;
		annotationPreviewIndex=previewIndex;
		handleManagerSaved=new HandlerManager(null);  // create the handle manager for dispatch the onAnnotationMoved event when the user move the AnnotationTag
		handleManagerTextChange=new HandlerManager(null); // create the handle manager for dispatch the onTextChange event when the user change description on AnnotationTag
		handleManagerAnnotKeyWordBlur=new HandlerManager(null);// create the handle manager for dispatch the onAnnotationKeyWordBlur event when the user change description on AnnotationTag
		isOpened=true;    // set the annotation as visible and open
		addResizedHandler(new ResizedHandler() {
			public void onResized(ResizedEvent event) { // on resize the AnnotationTag the Text Area box must be resized 
				
				setDimmension();   // resize the annotation Text Area according to the new size of AnnotationTag
			}
		});
				
		//annotationTextContainer = new WidgetCanvas();	// create the annotationText container that contain the annotationArea text area box			
		
		this.setCanDragReposition(true);  // The AnnotationTag can be dragged and repositioned   
		this.setCanDragResize(true);  // The AnnotationTag can be resized
		/*
		 * There are different types of effects for showing dragging behavior 
		 * OUTLINE : An outline the size of the target object is moved, resized, etc.
		 * TARGET :  The target object is actually moved, resized, etc.
		 * */
		this.setDragAppearance(DragAppearance.TARGET); 		
		this.setChildrenSnapResizeToGrid(true); //If true, causes this canvas's children to snap to its grid when resizing.
		this.setOverflow(Overflow.HIDDEN);  // Content that extends beyond the widget's width or height is clipped (hidden).
		this.setMinHeight(85);  // set min height size
		this.setMinWidth(90);   // set min width size
		setSize("150px", "120px");
		addMouseOutHandler(new MouseOutHandler() {
			public void onMouseOut(MouseOutEvent event) {  //when the mouse leaves the AnnotationTag area change the style that hide the drag border
				setStyleName("AnnotationBox");	 // set the style that hide the drag border
				
			}
		});
		addMouseOverHandler(new MouseOverHandler() {
			public void onMouseOver(MouseOverEvent event) {  //when the mouse enter on the AnnotationTag area change the style that show the drag border
				setStyleName("AnnotationBoxSelected"); // set the style that show the drag border
			}
		});
		
		setLeft(xPos); // set the X position of AnnotationTag 
		setTop(yPos);  // set the Y position of AnnotationTag
		setStyleName("AnnotationBox");
	    setAlign(Alignment.CENTER);
	    
	    textArea = new TextArea();
	    
	    textArea.addDoubleClickHandler(new DoubleClickHandler() {
	    	public void onDoubleClick(DoubleClickEvent event) {  // on double click on Annotation Text area box, AnnotationTag must be closed
				isOpened=false;    // set the AnnotationTag as closed and invisible
				animateHide(AnimationEffect.FADE, null, animateDuration);	// run the AnnotationTag closing animation. 	
				handleManagerSaved.fireEvent(new AnnotationSaveEvent(annotationTimeStart,annotationTimeEnd,annotationPreviewIndex));  // fires the AnnotationSaveEvent event to inform event handler listeners.
			}
	    });
	    textArea.addKeyDownHandler(new KeyDownHandler() {
	    	public void onKeyDown(KeyDownEvent event) {
	    		setDimmension();
	    	}
	    });
	    
	    panelKeyword = new FlexTable();
	    addMember(panelKeyword);
	    panelKeyword.setSize("100%", "10%");
	    
	    Image imageKeyWord = new Image("Img/Icons/AnnotationImg/key.png");
	    panelKeyword.setWidget(0, 0, imageKeyWord);
	    imageKeyWord.setSize("15px", "15px");
	    panelKeyword.getCellFormatter().setHeight(0, 0, "15px");
	    panelKeyword.getCellFormatter().setWidth(0, 0, "15px");
	    
	    textBoxKeyword = new TextBox();
	    textBoxKeyword.addFocusHandler(new FocusHandler() {
	    	public void onFocus(FocusEvent event) {
	    		keyWordValue=textBoxKeyword.getText();
	    	}
	    });
	    textBoxKeyword.addBlurHandler(new BlurHandler() {
	    	public void onBlur(BlurEvent event) {
	    		boolean keyWordWasEmpty=false;  //if true annotation key word was empty. false otherwise.
	    		
	    		if(keyWordValue.compareTo(textBoxKeyword.getText())!=0){	    			
	    			if(keyWordValue.compareTo("")==0) keyWordWasEmpty=true;	    				
	    			handleManagerAnnotKeyWordBlur.fireEvent(new AnnotationKeywordBlurEvent(keyWordValue,textBoxKeyword.getText(),keyWordWasEmpty));
	    		}
	    	}
	    });
	    textBoxKeyword.addKeyUpHandler(new KeyUpHandler() {
	    	public void onKeyUp(KeyUpEvent event) {// on key up on Annotation Text area box, annotation preview label must be changed
	    		// fires the AnnotationDescrTextChangeEvent event to inform event handler listeners.
	    		handleManagerTextChange.fireEvent(new AnnotationDescrTextChangeEvent(annotationPreviewIndex,textBoxKeyword.getText()));
	    	}
	    });
	    textBoxKeyword.setStyleName("AnnotationPrevieTextBox");
	    textBoxKeyword.addDoubleClickHandler(new DoubleClickHandler() {
	    	public void onDoubleClick(DoubleClickEvent event) {
	    		Window.alert("width: " +getOffsetWidth() + " Heigth: " +getOffsetHeight());
	    	}
	    });
	    textBoxKeyword.setAlignment(TextAlignment.CENTER);
	    panelKeyword.setWidget(0, 1, textBoxKeyword);
	    textBoxKeyword.setSize("100%", "10px");
	    panelKeyword.getCellFormatter().setHeight(0, 1, "10px");
	    panelKeyword.getCellFormatter().setWidth(0, 1, "90%");
	    panelKeyword.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
	    panelKeyword.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
	    
	    panelDescription = new FlexTable();
	    addMember(panelDescription);
	    panelDescription.setSize("100%", "90%");
	    
	    Image imageDescription = new Image("Img/Icons/AnnotationImg/descrizione.png");
	    panelDescription.setWidget(0, 0, imageDescription);
	    imageDescription.setSize("15px", "15px");
	    panelDescription.getCellFormatter().setHeight(0, 0, "15px");
	    panelDescription.getCellFormatter().setWidth(0, 0, "15px");
	    panelDescription.setWidget(0,1, textArea);
	    panelDescription.getCellFormatter().setHeight(0, 1, "100%");
	    panelDescription.getCellFormatter().setWidth(0, 1, "90%");
	    textArea.setSize("100%", "100%");
	    
	    lblSaStria = new Label("@SaStria");
	    lblSaStria.setHeight("20px");
	    lblSaStria.setAlign(Alignment.CENTER);
	    textArea.setStyleName("TextArea");
	    panelDescription.getCellFormatter().setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER);
	    panelDescription.getCellFormatter().setVerticalAlignment(0, 1, HasVerticalAlignment.ALIGN_MIDDLE);
	    panelDescription.getCellFormatter().setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_CENTER);
	    panelDescription.getCellFormatter().setVerticalAlignment(0, 0, HasVerticalAlignment.ALIGN_MIDDLE);
	    addMember(lblSaStria);
		this.animateShow(AnimationEffect.FADE, null, animateDuration);
		setDimmension();			
	}
	
	
	/**
	 * This method sets the Annotation style name. AnnotationBoxSelected show a resize and drag and drop border.
	 *  AnnotationBoxSelected hide a resize and drag and drop border. 
	 * @param value : boolean value. If true set the AnnotationBoxSelected that display borders, false otherwise  
	 */
	public void setSelected(boolean value){
		if(value)
			this.setStyleName("AnnotationBoxSelected");
		else
			this.setStyleName("AnnotationBox");
	}
	
	
	/**
	 * This method get AnnotationTag selected status according to stylename value.  
	 * @return boolean value. If true AnnotationTag has focus and "AnnotationBoxSelected"
	 * is the current style. false otherwise.
	 */
	public boolean getSelected(){
		boolean returnValue;
		if(this.getStyleName().compareTo("AnnotationBoxSelected")==0) // if stylename is AnnotationBoxSelected then Annotation tag has focus
			returnValue=true;
		else
			returnValue=false;
		return(returnValue);
	}
	
	
	/**
	 * This method force the AnnotaionTag draw and open. The opening/drawing process is realized as
	 * an animation that draw the AnnotationTag slowly.   
	 */
	public void forceDraw(){
		isOpened=true;
		this.animateShow(AnimationEffect.FADE, null, animateDuration);
	}
	
	
	/**
	 * This method force the AnnotaionTag close and hide. The hiding/closing process is realized as
	 * an animation that hide the AnnotationTag slowly.
	 */
	public void forceHide(){
		isOpened=false;
		this.animateHide(AnimationEffect.FADE, null, animateDuration);		
	}
	
	
	/**
	 * This method gets the visible status of AnnotaionTag 
	 * @return boolean value: if true the AnnotationTag is visible, false otherwise
	 */
	public boolean getIsVisible(){
		return(isOpened);
	}
	
	
	/**
	 * This method add a AnnotationSaveEventHandler handler. This is executed when a double
	 * click of mouse occurs on AnnotationTag
	 * @param handler: the AnnotationSaveEventHandler handler
	 */
	public void addAnnotationSaveHandler(AnnotationSaveEventHandler handler){
		handleManagerSaved.addHandler(AnnotationSaveEvent.TYPE, handler);
	}
	

	 /**
	 * This method add a AnnotationDescrTextChangeEventHandler handler. This is executed when the annotation
	 * description change on AnnotationTag
	 * @param handler: the AnnotationDescrTextChangeEventHandler handler
	 */
	public void addAnnotationDescrTextChange(AnnotationDescrTextChangeEventHandler handler){
		handleManagerTextChange.addHandler(AnnotationDescrTextChangeEvent.TYPE, handler);
	}
	

	/**
	 * This method add a AnnotationKeywordBlurEventHandler handler. This is executed when the annotation
	 * description change on AnnotationTag
	 * @param handler: the AnnotationKeywordBlurEventHandler handler
	 */
	public void addAnnotationKeyWordBlur(AnnotationKeywordBlurEventHandler handler){
		handleManagerAnnotKeyWordBlur.addHandler(AnnotationKeywordBlurEvent.TYPE, handler);
	}
	
	
	
	
	/**
	 * This method add a string to the current word showed on labelSaStria.
	 * @param value: String to add at the current word showed on labelSaStria.
	 */
	@Deprecated 
	public void addContentToLabelSaStria(String value){
		//labelSaStria.setContents(labelSaStria.getContents() + "-" + value);
	}
	
	
	/**
	 * This method set the content value of AnnotationTag and in particular mode
	 * sets the text to display on Annotation Text Box Area. 
	 * @param value
	 */
	public void setContentValue(String value){
	 // annotationArea.setText(value);
	}
	
	/**
	 * Sets annotation video segment end time.
	 * @param timeValue double value indicating annotation video segment end time.
	 */
	public void setTimeEnd(double timeValue){
		annotationTimeEnd=timeValue;
	}
	
	/**
	 * Gets annotation video segment Start time.
	 * @return timeValue double value indicating annotation video segment start time.
	 * 
	 */
	public double getTimeStart(){
		return(annotationTimeStart);
	}
	
	/**
	 * Gets annotation video segment end time.
	 * @return timeValue double value indicating annotation video segment end time.
	 */
	public double getTimeEnd(){
		return(annotationTimeEnd);
	}
	/**
	 * Sets annotation video segment start time.
	 * @param timeValue double value indicating annotation video segment end time.
	 */
	public void setTimeStart(double timeValue){
	annotationTimeStart=timeValue;
	}
	
	/**
	 * Sets annotation video segment start and end time.
	 * @param timeValueStart
	 * @param timeValueEnd
	 */
	public void setTimesegment(double timeValueStart,double timeValueEnd){
		setTimeStart(timeValueStart);
		setTimeEnd(timeValueEnd);
	}
}
